/**
 * Created by huangzx on 2015/6/8.
 */
define('framework/msg/GillionMsgModule', [
    'angular',
    'jquery'
], function (angular, $) {
    return angular.module('GillionMsgModule', [])
        .factory('GillionMsg', ['$timeout', function($timeout) {
            var msgBoxCache = {},
                currZIndex = 999,
                htmlTemplate = '<div class="modal-dialog">\n    <div class="modal-content">\n        <div class="modal-header">\n            <h4 class="modal-title"></h4>\n        </div>\n        <div class="modal-body">\n            <p></p>\n        </div>\n        <div class="modal-footer">\n        </div>\n    </div>\n</div>',
                //按钮样式配置
                btnTypes = {
                    sure: '<button class="btn btn-default btn-fi"><i class="fi fi-sumbit"></i></button>',
                    cancel: '<button class="btn btn-default btn-important"></button>',
                    default: '<button class="btn btn-default"></button>'
                },
                //icon图标样式
                iconTypes = {
                    right: '<i class="fi fi-right"></i>',
                    error : '<i class="fi fi-error"></i>',
                    confirm: '<i class="fi fi-confirm"></i>'
                };

            /**
             * 构造一个按钮对象
             * @param opts {Object}
             *   [opts.text] {String} 按钮文本
             *   [opts.type] {String} 按钮样式类型
             *   [opts.handler] {function} 按钮点击事件,返回false则不处理默认事件关闭弹框
             * @param owner {Object} 按钮所在弹框
             */
            function buildButton(opts, owner) {
                var $btn, handler;
                if(!angular.isObject(opts)) return;
                handler = opts.handler;
                $btn = angular.element(btnTypes[opts.type] || btnTypes['default']);
                $btn.append(opts.text).click(function(){
                    var flag;
                    if (angular.isFunction(handler)) {
                        flag = handler();
                        if (flag === false) return;
                    }
                    owner.close();
                });
                return $btn;
            }

            /**
             * 消息框构造函数
             * @constructor
             */
            function MsgBox(opts) {
                this.opts = opts;
                this.$ele = angular.element(htmlTemplate);
                this.tempId = 'msgBox'+ new Date().getTime();
            }
            /**
             * 遮罩
             */
            MsgBox.prototype.mask = function(){
                var $ele = this.$ele,
                    $mask;
                if (!this.$mask) {
                    $mask = this.$mask = angular.element('<div class="modal-mask"></div>');
                    $mask.appendTo('body');
                }
                $mask.css('z-index', currZIndex++).show();
            };
            /**
             * 设置最大宽度
             * @param val {Number}
             */
            MsgBox.prototype.setMaxWidth = function(val){
                var $ele = this.$ele;
                $ele.css('max-width', val);
            };
            /**
             * 设置最大高度
             * @param val {Number}
             */
            MsgBox.prototype.setMaxHeight = function(val){
                var $ele = this.$ele;
                $ele.css('max-height', val);
            };
            /**
             * 设置最小宽度
             * @param val {Number}
             */
            MsgBox.prototype.setMinWidth = function(val){
                var $ele = this.$ele;
                $ele.css('min-width', val);
            };
            /**
             * 设置最小高度
             * @param val {Number}
             */
            MsgBox.prototype.setMinHeight = function(val){
                var $ele = this.$ele;
                $ele.css('min-height', val);
            };
            /**
             * 设置宽度
             * @param val {Number}
             */
            MsgBox.prototype.setWidth = function(val){
                var $ele = this.$ele;
                $ele.width(val);
            };
            /**
             * 设置高度
             * @param val {Number}
             */
            MsgBox.prototype.setHeight = function(val){
                var $ele = this.$ele;
                $ele.height(val);
            };
            /**
             * 设置标题
             * @param [title] {String} 标题文本
             */
            MsgBox.prototype.setTitle = function(title){
                var $ele = this.$ele;
                $ele.find('.modal-title').html(title);
            };
            /**
             * 设置消息
             * @param [msg] {String} 消息文本
             */
            MsgBox.prototype.setMsg = function(msg){
                var $ele = this.$ele;
                $ele.find('.modal-body p').html(msg);
            };
            /**
             * 从iframe中加载一个页面
             * @param url
             */
            MsgBox.prototype.setUrl = function(url){
                var $ele = this.$ele,
                    width = $ele.width() - 40,
                    heigth = $ele.height() - 80;
                $ele.find('.modal-body').html('<iframe width="'+width+'" height="'+heigth+'" src="'+url+'" frameborder="0"/>');
            };
            /**
             * 设置icon图标
             * @param icon {String}
             */
            MsgBox.prototype.setIcon = function(icon){
                var $ele = this.$ele;
                if (iconTypes[icon]) {
                    $ele.find('.modal-body')
                        .addClass('modal-body-fi')
                        .prepend(iconTypes[icon]);
                }
            };
            /**
             * 设置关闭
             */
            MsgBox.prototype.setClosable = function(){
                var self = this,
                    $ele = self.$ele,
                    $closeBtn;
                $closeBtn = angular.element('<button class="btn btn-default"><i class="fi fi-close"></i></button>');
                $ele.find('.modal-header').prepend($closeBtn);
                $closeBtn.click(function(){
                    self.close();
                });
            };

            /**
             * 等待条
             */
            MsgBox.prototype.wait = function(){
                var $ele = this.$ele;
                $ele.find('.modal-body').prepend('<div class="waiting"><img src="'+ window.ctx + '/static/images/waitpls.gif"/></div>');
                $ele.find('.modal-body p').addClass('waiting');
            };

            /**
             * 显示进度条
             */
            MsgBox.prototype.progress = function(){
                var self = this,
                    $ele = this.$ele;
                $ele.find('.modal-body').prepend(
                    '<div class="progress">\n    <div class="progress-bar" role="progressbar" style="width: 0%;">\n    </div>\n</div>\n<div class="progress-text">0%</div>'
                );
            };

            /**
             * 更新带有进度条的消息框中的文本和进度条
             * @param value {Number}
             * @param [progressText] {String}
             */
            MsgBox.prototype.updateProgress = function(value, progressText) {
                var $ele = this.$ele,
                    $porcessBar = $ele.find('.progress-bar'),
                    $porcessText= $ele.find('.progress-text');
                value = value<0?0:value>100?100:value;
                value = value + '%';
                if(!progressText) progressText = value;
                $porcessBar.css('width', value);
                $porcessText.html(progressText);
            };

            /**
             * 初始化按钮组
             * @param buttons
             */
            MsgBox.prototype.initButtons = function(buttons) {
                var self = this,
                    $ele = self.$ele,
                    $footer;
                if(!angular.isArray(buttons)) return;
                $footer =  $ele.find('.modal-footer');
                angular.forEach(buttons, function(button){
                    $footer.append(buildButton(button, self));
                })
            };

            /**
             * 关闭
              */
            MsgBox.prototype.close = function() {
                var $ele = this.$ele,
                    $mask = this.$mask,
                    opts = this.opts,
                    onBeforeClose = opts.onBeforeClose,
                    onClose = opts.onClose;
                if (angular.isFunction(onBeforeClose) &&
                    onBeforeClose() === false) {
                    return;
                }
                $ele.remove();
                msgBoxCache[this.tempId] = null;
                $mask && $mask.remove();
                angular.isFunction(onClose) && onClose();
            };

            /**
             * 渲染
             */
            MsgBox.prototype.render = function() {
                var $ele = this.$ele,
                    opts = this.opts,
                    onBeforeOpen = opts.onBeforeOpen,
                    onOpen = opts.onOpen;

                if (angular.isFunction(onBeforeOpen) &&
                    onBeforeOpen() === false) {
                    return;
                }

                opts.modal && this.mask();
                $ele.appendTo('body');
                //强制居中布局
                $ele.css({
                    'position': 'absolute',
                    'left': '50%',
                    'top': '50%',
                    'margin-left':-($ele.width()/2),
                    'margin-top':-($ele.height()/2),
                    'z-index':currZIndex++
                });
                msgBoxCache[this.tempId] = this;
                angular.isFunction(onOpen) && onOpen();
            };

            /**
             * 返回jquery包装后的Iframe对象
             * @return [jquery(Iframe)]
             */
            MsgBox.prototype.getIframe = function(){
                var $ele = this.$ele;
                return $ele.find('iframe');
            };

            return {
                /**
                 * 基于给定的配置选项显示一个消息框
                 * @param options 配置项
                 *      [options.title='自定义标题'] {String} 标题
                 *      [options.msg='自定义内容'] {String} 内容
                 *      [options.closable=true] {Boolean} 右上关闭按钮
                 *      [options.modal=true] {Boolean} 遮罩
                 *      [options.timeout=0] {Number} 自动关闭，0表示不自动关闭
                 *      [options.icon] {String} icon图标
                 *      [options.width] {Number} 宽度
                 *      [options.height] {Number} 高度
                 *      [options.maxWidth] {Number} 最大宽度
                 *      [options.maxHeight] {Number} 最大高度
                 *      [options.minWidth] {Number} 最小宽度
                 *      [options.minHeight] {Number} 最小高度
                 *      [options.onBeforeClose] {Function} 关闭之前事件，返回false可以取消关闭操作
                 *      [options.onClose] {Function} 关闭后事件
                 *      [options.onBeforeOpen] {Function} 打开前事件，返回false可以取消打开操作
                 *      [options.onOpen] {Function} 打开后事件
                 *      [options.buttons] {Array} 按钮数组
                 *             按钮对象结构为{Object}
                 *             {
                 *                  text：'按钮文本',
                 *                  type: '按钮样式类型', //目前为'sure' or 'cancel' or 'default'
                 *                  handler: {Fnction} //按钮点击事件,返回false则不处理默认事件关闭弹框
                 *             }
                 *  @return {MsgBox} 弹框对象，带有close方法关闭弹框
                 */
                show: function(options) {
                    var msgBox,
                        opts = {
                            title: '自定义标题',
                            msg: '自定义内容',
                            closable:true,
                            modal: true,
                            width : 300,
                            timeout: 0
                        };
                    angular.extend(opts, options);
                    msgBox = new MsgBox(opts);
                    //控件初始化配置
                    msgBox.setTitle(opts.title);
                    msgBox.setMsg(opts.msg);
                    msgBox.initButtons(opts.buttons);
                    opts.icon && msgBox.setIcon(opts.icon);
                    opts.closable && msgBox.setClosable();
                    opts.width && msgBox.setWidth(opts.width);
                    opts.height && msgBox.setHeight(opts.height);
                    opts.maxWidth && msgBox.setMaxWidth(opts.maxWidth);
                    opts.maxHeight && msgBox.setMaxHeight(opts.maxHeight);
                    opts.minWidth && msgBox.setMinWidth(opts.minWidth);
                    opts.minHeight && msgBox.setMinHeight(opts.minHeight);
                    msgBox.render();

                    //设置是否自动关闭
                    if (opts.timeout && opts.timeout > 0) {
                        $timeout(function(){
                            msgBox.close();
                        }, opts.timeout);
                    }

                    //进度条的情况则返回该对象，方便后续调用关闭等操作
                    opts.wait && msgBox.wait();
                    opts.progress && msgBox.progress();
                    return msgBox;
                },

                /**
                 * 弹框，包含一个确定按钮
                 * @param [title='提示信息'] {String} 标题文本
                 * @param [msg='这是一个提示弹框！'] {String} 消息框内容
                 * @param [fn] {Function} 关闭后回调
                 * @param [options] {Object} 配置项
                 *      [options.icon] {String} icon图标
                 *      [options.closable=true] {Boolean} 右上关闭按钮
                 *      [options.modal=true] {Boolean} 遮罩
                 *      [options.timeout=0] {Number} 自动关闭，0表示不自动关闭
                 *      [options.width] {Number} 宽度
                 *      [options.height] {Number} 高度
                 *      [options.maxWidth] {Number} 最大宽度
                 *      [options.maxHeight] {Number} 最大高度
                 *      [options.minWidth] {Number} 最小宽度
                 *      [options.minHeight] {Number} 最小高度
                 */
                alert: function(title, msg, fn, options) {
                    options = options || {};
                    angular.extend(options, {
                        title: title || '提示信息',
                        msg: msg || '这是一个提示弹框！',
                        buttons: [{
                            text:'确定',
                            type:'sure',
                            handler: fn
                        }]
                    });
                    this.show(options);
                },

                /**
                 * 确认框，包含一个确定和取消按钮
                 * @param [title='确认信息'] {String} 标题文本
                 * @param [msg='这是一个确认弹框！'] {String} 消息框内容
                 * @param [fn] {Function} fn(b) 当用户点击“确定”按钮的时侯将传递一个true值给回调函数，否则传递一个false值。
                 * @param [options] {Object} 配置项
                 *      [options.icon=''] {String} icon图标
                 *      [options.closable=true] {Boolean} 右上关闭按钮
                 *      [options.modal=true] {Boolean} 遮罩
                 *      [options.timeout=0] {Number} 自动关闭，0表示不自动关闭
                 *      [options.width] {Number} 宽度
                 *      [options.height] {Number} 高度
                 *      [options.maxWidth] {Number} 最大宽度
                 *      [options.maxHeight] {Number} 最大高度
                 */
                confirm: function(title, msg, fn, options){
                    options = options || {};
                    angular.extend(options, {
                        title: title || '确认信息',
                        msg: msg || '这是一个确认弹框！',
                        buttons: [{
                            text:'确定',
                            type: 'sure',
                            handler: function(){
                                angular.isFunction(fn) && fn(true);
                            }
                        },{
                            text:'取消',
                            type: 'cancel',
                            handler: function(){
                                angular.isFunction(fn) && fn(false);
                            }
                        }]
                    });
                    this.show(options);
                },

                /**
                 * 显示一个等待进度条
                 * @param ［title='请等待'］ {String} 进度条文本
                 * @param msg {String}
                 * @param [modal] {Boolean} 模态效果
                 * @returns {MsgBox}
                 */
                wait: function(title, msg, modal){
                    return this.show({
                        wait: true,
                        title: title || '请等待',
                        msg: msg || '',
                        modal: modal
                    });
                },

                /**
                 * 显示一个百分比进度条
                 * @param [title='正在提交'] {String}
                 * @param msg {String}
                 * @param [modal] {Boolean}
                 * @returns {MsgBox}
                 */
                progress: function(title, msg, modal){
                    return this.show({
                        progress: true,
                        title: title || '正在提交',
                        msg: msg || '',
                        modal: modal
                    });
                },

                /**
                 * 用iframe打开一个页面
                 * @param [title or options] {String or Object} 标题 或 配置项
                 *      [options.title='自定义标题'] {String} 标题
                 *      [options.url] {String} 打开的iframe页面
                 *      [options.data] {obj} 向url传递的json对象，
                 *      [options.closable=true] {Boolean} 右上关闭按钮
                 *      [options.modal=true] {Boolean} 遮罩
                 *      [options.width] {Number} 宽度
                 *      [options.height] {Number} 高度
                 *      [options.onBeforeClose] {Function} 关闭之前事件，返回false可以取消关闭操作
                 *      [options.onClose] {Function} 关闭后事件
                 *      [options.onBeforeOpen] {Function} 打开前事件，返回false可以取消打开操作
                 *      [options.onOpen] {Function} 打开后事件
                 *  @param [url] {String} 打开的页面
                 *  @param [width] {Number} 宽度
                 *  @param [height] {Number} 高度
                 *  @param [modal=true] {Boolean} 模态效果
                 *  @return {MsgBox} 弹框对象，带有close方法关闭弹框
                 */
                showUrl: function (title, url, data, width, height) {
                    var msgBox,
                        opts = {
                            title: 'IFRAME弹出框',
                            closable:true,
                            width: width || 500,
                            height:height || 300,
                            modal: true
                        };

                    if (angular.isObject(title)) {
                        angular.extend(opts, title);
                        url = opts.url;
                        data = opts.data;
                    } else {
                        opts.title = title;
                    }
                    if (!angular.isString(url)) return;

                    msgBox = new MsgBox(opts);
                    msgBox.setTitle(opts.title);
                    opts.closable && msgBox.setClosable();
                    msgBox.setWidth(opts.width);
                    msgBox.setMaxWidth(opts.width);
                    msgBox.setHeight(opts.height);
                    msgBox.setMaxHeight(opts.height);
                    if (angular.isObject(data)) {
                        url = url.indexOf('?') > 0?url.indexOf('?') > 0:
                            url = url+'?'+ $.param(opts.data);
                    }
                    msgBox.setUrl(url);
                    msgBox.render();
                    return msgBox;
                }
            };
        }])
        .directive('gMsg', ['GillionMsg', function(GillionMsg){
            return {
                restrict: 'A',
                scope: {
                    options:'=',
                    fn:'='
                },
                link: function(scope, ele, attrs){
                    ele.click(function(){
                        var invokeName = attrs.gMsg,
                            options = scope.options || {},
                            fn = scope.fn,
                            title = attrs.title,
                            msg = attrs.msg;
                        angular.extend(options, {
                            title: title,
                            msg: msg
                        })
                        if (!invokeName || invokeName=='show' || !angular.isFunction(GillionMsg[invokeName])) {
                            GillionMsg.show(options);
                        } else {
                            GillionMsg[invokeName](title, msg, fn, options);
                        }
                    });
                }
            };
        }]);
});